-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
loosen number index check, fixes #15768 #17767
loosen number index check, fixes #15768 #17767
Conversation
@tycho01, |
src/compiler/checker.ts
Outdated
const typeOrConstraint = (tp: Type) => maybeTypeOfKind(tp, TypeFlags.TypeVariable) ? getBaseConstraintOfType(tp) || tp : tp; | ||
if (isTypeAssignableToKind(typeOrConstraint(indexType), TypeFlags.NumberLike) && | ||
getIndexInfoOfType(typeOrConstraint(objectType), IndexKind.Number)) { | ||
return type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change this to just:
if (getIndexInfoOfType(getApparentType(objectType), IndexKind.Number) && isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) {
return type;
}
Otherwise PR looks good. Thanks!
Fixed. That's definitely even cleaner! 😅 |
I might be late to the party but this doesn't seem right. When the index is out of range, the result is a union of all constituents. While that's how expression level tuples work, it's not correct and we shouldn't spread misleading behaviour to the type level. type X<I extends number> = ['a'][I];
type Test = X<1>// 'a' :/ |
@gcnew: see also On another note, I do still get a few |
@tycho01 Yes, you are right. Unfortunately it's been broken and you've made it more consistent. In this case 👍. |
@gcnew: I gave the issue you raised a bit more thought.
I think the root question here is what the index types are for. There appear to be three use-cases:
I do suppose all of this only goes to show you're right that current behavior for tuples may not be ideal. I'm not surprised about the current behavior in the sense it just got this index behavior from Breaking changes would probably all get flags if they get in at all, and I do wonder about the potential impact (both positive and negative) of such a change -- or what the desired behavior should be at all. Not that I oppose changes, hopefully (under flags) we can add in all the more ideal behavior. tl;dr elaborate? what would you prefer and why? Edit: to explain my confusion, the alternatives each have issues:
Do those last ideas match what you'd been hoping for there? I'm pretty neutral here, just curious. |
I think it would have been best if tuples behaved like object with their indices as keys. All the normal object rules should be in effect. For example, the indexing type variable should be a // ['syntax', true] => { 0: 'syntax', 1: true }
type Tup = ['syntax', true]
type T1<I> = Tup[I] // error
type T2<I extends number> = Tup[I] // error
type T2<I extends keyof Tup> = Tup[I] // OK
type T2<I extends number> = (Tup & { [k: number]: undefined })[I] // OK On a side note, I don't think tuples should be a subclass of |
I guess, yeah. Complication from recent experience: in my fixed Unfortunately I squashes out those commits though, and I guess a couple methods already aren't compatible; there may be a way I guess. |
see title
Edit by @DanielRosenwasser: Fixes #15768